package com.qyer.search.storm.util;

/**
 * Created by tangzheng on 16/5/31.
 */

import com.qyer.search.storm.logging.InfoLogger;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.*;
/**
 * Created by tangzheng on 16/1/11.
 */
public class CommonZTagService implements Runnable{
  private InfoLogger dataLog;

  private volatile static CommonZTagService singleton;
  private List<Map<Integer, List<ZTag>>> ztagList;
  private Thread thread;
  private String dBurl;
  private String user;
  private String pass;
  private String sql;
  private Connection conn = null;
  int chose = 0;

  private AtomicBoolean _shutdown;

  private CommonZTagService (Map<String, Object> config, String boltPrefix, String stormInfo){
    dataLog = new InfoLogger("/Data/search/CommonZTagService/" + stormInfo +"_ztag", stormInfo + "_data");
    Map<Integer, List<ZTag>> z0 = new HashMap<>(250);
    Map<Integer, List<ZTag>> z1 = new HashMap<>(250);
    ztagList = new ArrayList<>();
    ztagList.add(z0);
    ztagList.add(z1);
    _shutdown = new AtomicBoolean(false);
    chose = 0;
    dBurl = String.valueOf(config.get(boltPrefix + "db.mysql.url"));
    user = String.valueOf(config.get(boltPrefix + "db.mysql.user"));
    pass = String.valueOf(config.get(boltPrefix + "db.mysql.password"));
    //sql = "select bc.tag_id,a.tag_name,bc.c_id,bc.category_name,bc.category_type from (select id,tag_name from qyer_lastminute.zworld_tag where state = 1) a join (select c.tag_id,b.id as c_id,b.category_name,b.category_type from (select id,category_name,category_type from qyer_lastminute.zworld_category where state = 1) b join (select category_id,tag_id from qyer_lastminute.zworld_category_tag where state = 1) c on b.id = c.category_id) bc on a.id = bc.tag_id;";
    sql = "select a.id,a.tag_name,bc.c_id,bc.category_name,bc.category_type from (select id,tag_name from qyer_lastminute.zworld_tag where state = 1 and id != 153 and id != 154) a left join (select c.tag_id,b.id as c_id,b.category_name,b.category_type from (select id,category_name,category_type from qyer_lastminute.zworld_category where state = 1) b join (select category_id,tag_id from qyer_lastminute.zworld_category_tag where state = 1) c on b.id = c.category_id) bc on a.id = bc.tag_id;";
    try {
      Class.forName("com.mysql.jdbc.Driver");
      conn = java.sql.DriverManager.getConnection(dBurl, user, pass);
      Statement stmt = conn.createStatement();
      ResultSet res = stmt.executeQuery(sql);
      int tag_id = 0;
      String tag_name = null;
      int c_id = -1;
      int pc_id = -1;
      String c_name = null;
      Map<Integer, List<ZTag>> tmp = ztagList.get(chose);
      List<ZTag> tmpL = null;
      while (res.next()){
        tag_id = res.getInt(1);
        tag_name = res.getString(2);
        if(res.getObject(3) != null){
          c_id = res.getInt(3);
          c_name = res.getString(4);
          pc_id  = res.getInt(5);
        }else {
          c_id = -1;
          pc_id = -1;
          c_name = null;
        }

        if(tmp.containsKey(tag_id)){
          tmpL = tmp.get(tag_id);
          tmpL.add(new ZTag(tag_id, tag_name, c_id, pc_id));
        }else {
          tmpL = new ArrayList<>(2);
          tmpL.add(new ZTag(tag_id, tag_name, c_id, pc_id));
          tmp.put(tag_id, tmpL);
        }
      }
    }catch (Exception e){
      dataLog.info("country map get failed,{}", e);
    }

    thread = new Thread(this, "countryService" + stormInfo);
    thread.start();

    dataLog.info("country service thread start.");
  }
  public static CommonZTagService getInstance(Map<String, Object> config, String boltPrefix, String stormInfo) {
    if (singleton == null) {
      synchronized (CommonZTagService.class) {
        if (singleton == null) {
          singleton = new CommonZTagService(config, boltPrefix, stormInfo);
        }
      }
    }
    return singleton;
  }

  @Override public void run() {

    int seconds = 0;
    try {
      while (!_shutdown.get()) {
        checkConn();
        if(seconds == 300000) {
          Statement stmt = conn.createStatement();
          ResultSet res = stmt.executeQuery(sql);
          /*
          */
          int tag_id = 0;
          String tag_name = null;
          int c_id = -1;
          int pc_id = -1;
          String c_name = null;
          Map<Integer, List<ZTag>> tmp = ztagList.get(1 - chose);
          tmp.clear();
          List<ZTag> tmpL = null;
          ////////////////////////
          while (res.next()) {
            tag_id = res.getInt(1);
            tag_name = res.getString(2);
            if(res.getObject(3) != null){
              c_id = res.getInt(3);
              c_name = res.getString(4);
              pc_id  = res.getInt(5);
            }else {
              c_id = -1;
              pc_id = -1;
              c_name = null;
            }

            if(tmp.containsKey(tag_id)){
              tmpL = tmp.get(tag_id);
              tmpL.add(new ZTag(tag_id, tag_name, c_id, pc_id));
            }else {
              tmpL = new ArrayList<>(2);
              tmpL.add(new ZTag(tag_id, tag_name, c_id, pc_id));
              tmp.put(tag_id, tmpL);
            }
          }
          chose = 1 - chose;
          seconds = 0;
        }
        Thread.sleep(10000);
        seconds += 10000;
      }
    }catch (Exception e){
      dataLog.info("interrupt by {}", e);
    }
  }

  private void checkConn(){
    try {
      if((conn == null) || (!conn.isValid(1))){
        dataLog.info("mysqlconnection is invalid,rebuild follow.");

        Connection _tempConn = conn;
        this.conn = getConnection(dBurl, user, pass);
        if(_tempConn != null) {
          _tempConn.close();
          dataLog.info("close the past mysqlconnection.");
        }
      }else {
        dataLog.info("mysqlconnection is ok");
      }
    }catch (Exception e){
      e.printStackTrace();
      dataLog.info("mysqlconnection rebuild failed by {}.", e);
      dataLog.info("Exception:{},DB connection invalid.", e.getMessage());
    }
  }

  private Connection getConnection(String dBurl, String user, String pass){
    try {
      Class.forName("com.mysql.jdbc.Driver");
      return java.sql.DriverManager.getConnection(dBurl, user, pass);
    }catch (Exception e){
      dataLog.info("get mysql connection failed.Exception is {}", e);
      return null;
    }
  }

  public void shutdown(){

    if(_shutdown.compareAndSet(false, true)) {
      try {
        if (conn != null)
          conn.close();
      } catch (Exception e) {
        dataLog.info("during shutdown,mysql connection shutdown failed.");
      }
      thread.interrupt();
    }
  }

  public List<ZTag> getZTags(int tag_id){
    return ztagList.get(chose).get(tag_id);
  }


}
